import ora from "ora";
import inquirer from "inquirer";
import chalk from "chalk";
import downloadGitRepo from "download-git-repo";
import util from "util";
import path from "path";
import { repos } from "./templates.js";

// 添加加载动画
async function wrapLoading(fn, message, ...args) {
  // 使用 ora 初始化，传入提示信息 message
  const spinner = ora(message);
  // 开始加载动画
  spinner.start();
  console.log(...args);
  try {
    // 执行传入方法 fn
    const result = await fn(...args);
    // 状态为修改为成功
    spinner.succeed();
    return result;
  } catch (error) {
    // 状态为修改为失败
    spinner.fail("Request failed, refetch ...");
  }
}
class Generator {
  constructor(name, targetDir) {
    // 目录名称
    this.name = name;
    // 创建位置
    this.targetDir = targetDir;
    // 改造 download-git-repo 支持 promise
    this.downloadGitRepo = util.promisify(downloadGitRepo);
  }
  async getRepo() {
    // 1）用户选择自己新下载的模板名称
    const { repo } = await inquirer.prompt({
      name: "repo",
      type: "list",
      choices: repos.map((config) => {
        return {
          value: config.name,
          name: config.message,
        };
      }),
      message: "Please choose a type to create project",
    });

    // 3）return 用户选择的名称
    return repo;
  }
  async getTemplate(repo) {
    const tems = repos.find((config) => config.name === repo);
    // 1）用户选择自己新下载的模板名称
    const { name } = await inquirer.prompt({
      name: "name",
      type: "list",
      choices: tems.templates.map((config) => {
        return {
          value: config.name,
          name: config.message,
        };
      }),
      message: "Please choose a template to create project",
    });
    // 3）return 用户选择的名称
    return tems.templates.find((config) => config.name === name).github;
  }
  // 下载远程模板
  // 1）拼接下载地址
  // 2）调用下载方法
  async download(temUrl) {
    // 1）拼接下载地址
    const requestUrl = temUrl;

    // 2）调用下载方法
    await wrapLoading(
      this.downloadGitRepo, // 远程下载方法
      "waiting download template", // 加载提示信息
      requestUrl, // 参数1: 下载地址
      path.resolve(process.cwd(), this.targetDir)
    ); // 参数2: 创建位置
  }
  // 核心创建逻辑
  // 1）获取模板名称
  // 2）获取 tag 名称
  // 3）下载模板到模板目录
  async create() {
    // 1）获取模板名称
    const repo = await this.getRepo();
    const temUrl = await this.getTemplate(repo);
    // 2）下载模板到模板目录
    await this.download(temUrl);

    console.log(`\r\nSuccessfully created project ${chalk.cyan(this.name)}`);
    console.log(`\r\n  cd ${chalk.cyan(this.name)}`);
    console.log("  npm run dev 或 yarn dev 或 pnpm dev\r\n");
  }
}

export default Generator;
